﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;

namespace EcologyFuture.Helper
{
  /// <summary>
  /// <c>WebHelper</c> class contains help methods for web manipulations.
  /// </summary>
  class WebHelper
  {
    /// <summary>
    /// Returns data from URI in Stream representation.
    /// </summary>
    /// <param name="uri">Unified resource identificator.</param>
    /// <returns>Data from URI as Stream.</returns>
    public static Stream GetDataFromUri(string uri)
    {
      try
      {
        WebRequest pageRequest = WebRequest.Create(uri);
        WebResponse pageResponse = pageRequest.GetResponse();
        return pageResponse.GetResponseStream();
      }
      catch (WebException e)
      {
        Console.WriteLine("WebExeption was throwed: " + e.Message);
        throw (new EFExeption());
      }
    }
  }
  /// <summary>
  /// <c>DateTimeHelper</c> class contains help methods for date and time manipulations.
  /// </summary>
  class DateTimeHelper
  {
    /// <summary>
    /// Returns string representation of offset to UTC for specified time zone.
    /// </summary>
    /// <param name="timeZone">String representation of time zone.</param>
    /// <returns>Offset for specified time zone.</returns>
    /// <example>"EEST" -> "+0300"</example>
    public static string GetOffsetByTimeZone(string timeZone)
    {
      string offset = "";
      switch (timeZone)
      {
        case "A"   : offset = "+0100"; break; //Alpha Time Zone +1
        case "ACDT": offset = "+1030"; break; //Australian Central Daylight Time + 10:30
        case "ACST": offset = "+0930"; break; //Australian Central Standard Time + 9:30
        case "ADT" : offset = "-0300"; break; //Atlantic Daylight Time -3
        case "AEDT": offset = "+1100"; break; //Australian Eastern Daylight Time or Australian Eastern Summer Time +11
        case "AEST": offset = "+1000"; break; //Australian Eastern Standard Time +10
        case "AKDT": offset = "-0800"; break; //Alaska Daylight Time -8
        case "AKST": offset = "-0900"; break; //Alaska Standard Time -9
        case "AST" : offset = "-0400"; break; //Atlantic Standard Time -4
        case "AWDT": offset = "+0900"; break; //Australian Western Daylight Time +9
        case "AWST": offset = "+0800"; break; //Australian Western Standard Time + 8
        case "B"   : offset = "+0200"; break; //Bravo Time Zone +2
        case "BST" : offset = "+0100"; break; //British Summer Time + 1
        case "C"   : offset = "+0300"; break; //Charlie Time Zone +3
        case "CDT" : offset = "-0500"; break; //Central Daylight Time -5
        case "CST" : offset = "-0600"; break; //Central Standard Time -6
        case "CEDT": offset = "+0200"; break; //Central European Daylight Time + 2
        case "CEST": offset = "+0200"; break; //Central European Summer Time +2
        case "CET" : offset = "+0100"; break; //Central European Time +1
        case "CXT" : offset = "+0700"; break; //Christmas Island Time +7
        case "D"   : offset = "+0400"; break; //Delta Time Zone +4
        case "E"   : offset = "+0500"; break; //Echo Time Zone +5
        case "EDT" : offset = "-0400"; break; //Eastern Daylight Time -4
        case "EST" : offset = "-0500"; break; //Eastern Standard -5 
        case "EEST":                          //Eastern European Summer Time +3
        case "EEDT": offset = "+0300"; break; //Eastern European Daylight Time +3
        case "EET" : offset = "+0200"; break; //Eastern European Time +2
        case "F"   : offset = "+0600"; break; //Foxtrot Time Zone +6
        case "G"   : offset = "+0700"; break; //Golf Time Zone+7
        case "H"   : offset = "+0800"; break; //Hotel Time Zone +8
        case "HAA" : offset = "-0300"; break; //Heure Avancee de l'Atlantique -3
        case "HAC" : offset = "-0500"; break; //Heure Avancee du Centre -5
        case "HADT": offset = "-0900"; break; //Hawaii-Aleutian Daylight Time -9
        case "HAE" : offset = "-0400"; break; //Heure Avancee de l'Est -4
        case "HAP" : offset = "-0700"; break; //Heure Avancee du Pacifique -7
        case "HAR" : offset = "-0600"; break; //Heure Avancee des Rocheuses -6
        case "HAST": offset = "-1000"; break; //Hawaii-Aleutian Standard Time-10
        case "HAT" : offset = "-0230"; break; //Heure Avancee de Terre-Neuve -2:30
        case "HAY" : offset = "-0800"; break; //Heure Avancee du Yukon -8;
        case "HNA" : offset = "-0400"; break; //Heure Normale de l'Atlantique -4
        case "HNC" : offset = "-0600"; break; //Heure Normale du Centre -6
        case "HNE" : offset = "-0500"; break; //Heure Normale de l'Est -5
        case "HNP" : offset = "-0800"; break; //Heure Normale du Pacifique -8
        case "HNR" : offset = "-0700"; break; //Heure Normale des Rocheuses -7
        case "HNT" : offset = "-0330"; break; //Heure Normale de Terre-Neuve -3:30
        case "HNY" : offset = "-0900"; break; //Heure Normale du Yukon -9
        case "HST" : offset = "-1000"; break; //Hawaii Standard Time -10
        case "I"   : offset = "+0900"; break; //India Time Zone +9
        case "IST" : offset = "+0100"; break; //Irish Summer Time +1;
        case "K"   : offset = "+1000"; break; //Kilo Time Zone +10
        case "L"   : offset = "+1100"; break; //Lima Time Zone +11
        case "M"   : offset = "+1200"; break; //Mike Time Zone +12
        case "MDT" : offset = "-0600"; break; //Mountain Daylight Time -6
        case "MESZ": offset = "+0200"; break; //Mitteleuroaische Sommerzeit +2
        case "MEZ" : offset = "+0100"; break; //Mitteleuropaische Zeit +1
        case "MSD" : offset = "+0400"; break; //Moscow Daylight Time +4
        case "MSK" : offset = "+0300"; break; //Moscow Standard Time +3
        case "MST" : offset = "-0700"; break; //Mountain Standard Time -7
        case "N"   : offset = "-0100"; break; //November Time Zone -1
        case "NDT" : offset = "-0230"; break; //Newfoundland Daylight Time -2:30
        case "NFT" : offset = "+1130"; break; //Norfolk (Island) Time +11:30
        case "NST" : offset = "-0330"; break; //Newfoundland Standard Time -3:30
        case "O"   : offset = "-0200"; break; //Oscar Time Zone -2
        case "P"   : offset = "-0300"; break; //Papa Time Zone -3
        case "PDT" : offset = "-0700"; break; //Pacific Daylight Time -7
        case "PST" : offset = "-0800"; break; //Pacific Standard Time -8
        case "Q"   : offset = "-0400"; break; //Quebec Time Zone -4
        case "R"   : offset = "-0500"; break; //Romeo Time Zone-5
        case "S"   : offset = "-0600"; break; //Sierra Time Zone -6
        case "T"   : offset = "-0700"; break; //Tango Time Zone -7
        case "U"   : offset = "-0800"; break; //Uniform Time Zone -8
        case "UT"  :                          //Universal Time
        case "UTS" :                          //Smoothed Universal Time
        case "GMT" : offset = "+0000"; break; //Greenwich Mean Time
        case "V"   : offset = "-0900"; break; //Victor Time Zone -9
        case "W"   : offset = "-1000"; break; //Whiskey Time Zone -10
        case "WDT" : offset = "+0900"; break; //Western Daylight Time+9
        case "WEDT": offset = "+0100"; break; //Western European Daylight Time +1
        case "WEST": offset = "+0100"; break; //Western European Summer Time +1
        case "WET" : offset = "+0000"; break; //Western European Time +0
        case "WST" : offset = "+0900"; break; //Western Summer Time +9
        case "X"   : offset = "-1100"; break; //X-ray Time Zone  -11
        case "Y"   : offset = "-1200"; break; //Yankee Time Zone-12
        case "Z"   : offset = "+0000"; break; //Zulu Time Zone +0
      }
      return offset;
    }
    /// <summary>
    /// Converts date and time from string representation to <c>DateTime</c> object.
    /// </summary>
    /// <param name="strDate">String represantation of date and time.</param>
    /// <returns><c>DateTime</c> object with date and dite in UTC.</returns>
    public static DateTime ParseDate(string strDate)
    {
      try
      {
        int index = strDate.LastIndexOf(' ') + 1;
        string timeZone = strDate.Substring(index);
        if (timeZone[0] != '+' && timeZone[0] != '-')
        {
          timeZone = GetOffsetByTimeZone(timeZone);
          strDate = strDate.Remove(index);
          strDate += timeZone;
        }
        DateTime convertedDate = DateTime.Parse(strDate);
        return convertedDate.ToUniversalTime();
      }
      catch (Exception)
      {
          throw (new EFExeption("Date parse exception."));
      }
    }
  }
  /// <summary>
  /// <c>EFException</c> class represents inner exceptions in EcologyFuture.
  /// </summary>
  public class EFExeption : ApplicationException
  {
    /// <summary>
    /// Initializes a new instance of the <c>EFException</c> class.
    /// </summary>
    public EFExeption() { }
    /// <summary>
    /// Initializes a new instance of the <c>EFException</c> class with a specified error message.
    /// </summary>
    /// <param name="message">Error message.</param>
    public EFExeption(string message) : base(message) { }
    /// <summary>
    /// Initializes a new instance of the <c>EFException</c> class with a specified error message
    /// and inner exception that cause this exception.
    /// </summary>
    /// <param name="message">Error message.</param>
    /// <param name="inner">Reference to inner exception.</param>
    public EFExeption(string message, Exception inner) : base(message) { }
  }
}
